<template>
  <div>
    <div class="input-editor" ref="inputEditor"></div>
    <div class="operate-bar">
      <el-button type="primary" @click="formatJson()">json格式化</el-button>
      <!-- 缩进 引号 复制 清空 -->
    </div>
    <div class="output-editor" ref="outputEditor"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { EditorView, basicSetup } from 'codemirror'
import { placeholder } from '@codemirror/view'
import { EditorState, Compartment } from '@codemirror/state'
import { json } from '@codemirror/lang-json'
import { ElMessage } from 'element-plus'
import 'element-plus/es/components/message/style/index'

let inputEditor = ref(),
  inputEditorView: any = null
onMounted(() => {
  inputEditorView = new EditorView({
    doc: '',
    extensions: [basicSetup, json(), placeholder('请输入json数据...')],
    parent: inputEditor.value
  })
  inputEditorView.focus()
})

let outputEditor = ref(),
  outputEditorView: any = null,
  language = new Compartment(),
  readOnly = new Compartment(),
  state = EditorState.create({
    doc: '',
    extensions: [
      basicSetup,
      language.of(json()),
      placeholder('json格式化后的结果'),
      readOnly.of(EditorState.readOnly.of(true))
    ]
  })
onMounted(() => {
  outputEditorView = new EditorView({
    state,
    parent: outputEditor.value
  })
})

const formatJson = () => {
  let inputContent = inputEditorView.state.doc.toString()
  if (!inputContent) {
    ElMessage.warning('请输入json数据')
    inputEditorView.focus()
    return
  }
  try {
    inputContent = JSON.stringify(JSON.parse(inputContent), null, 2)
  } catch (err) {
    ElMessage.error('JSON格式错误')
    return
  }
  outputEditorView.dispatch({
    changes: { from: 0, to: outputEditorView.state.doc.length, insert: inputContent }
  })
  ElMessage.success('JSON格式化成功')
}
</script>

<style lang="scss">
.cm-editor {
  height: 300px;
}
.input-editor,
.output-editor {
  box-shadow: var(--el-box-shadow-light);
}
.operate-bar {
  padding: 10px 0;
}
</style>
